package cn.toutatis.basics.notice


/*Kotlin 中使用关键字 class 声明类,主构造函数↓*/
class Example // 从 Any 隐式继承

/**
 * Any 有三个方法：equals()、 hashCode() 与 toString()。因此，为所有 Kotlin 类都定义了这些方法。
 * 默认情况下，Kotlin 类是最终（final）的：它们不能被继承。 要使一个类可继承，请用 open 关键字标记它。
 */
/*===================================================================================*/
open class Exp{

    /*如需重写方法,需要open关键字*/
    open fun say(): Unit {
        System.err.println("123")
    }

    open fun banRewrite(): Unit {
        System.err.println("如果需要在派生类禁止二次重写，可以在派生类添加final")
    }
}

class ExpExtend : Exp(){
    /*覆盖方法
    我们之前提到过，Kotlin 力求清晰显式。
    因此，Kotlin 对于可覆盖的成员（我们称之为开放）以及覆盖后的成员需要显式修饰符：*/
    override fun say(){
        System.err.println("456")
    }

    /*禁止ExpExtend类的派生类重写banRewrite方法*/
    final override fun banRewrite() {
        super.banRewrite()
    }
}


/*===================================================================================*/

/**
 * 在 Kotlin 中的一个类可以有一个主构造函数以及一个或多个次构造函数。
 * 主构造函数是类头的一部分：它跟在类名（与可选的类型参数）后。
 */
class ConstructorNotice constructor(name:String){

    /*主构造函数不能包含任何的代码。初始化的代码可以放到以 init 关键字作为前缀的初始化块（initializer blocks）中。
    * 请注意，初始化块中的代码实际上会成为主构造函数的一部分。
    * 委托给主构造函数会作为次构造函数的第一条语句，因此所有初始化块与属性初始化器中的代码都会在次构造函数体之前执行。
    * 即使该类没有主构造函数，这种委托仍会隐式发生，并且仍会执行初始化块：*/
    init {
        System.err.println("构造初始化")
    }

    private var index:Int = 0

    /*如果类有一个主构造函数，每个次构造函数需要委托给主构造函数， 可以直接委托或者通过别的次构造函数间接委托。
    委托到同一个类的另一个构造函数用 this 关键字即可：*/
    /*委托主构造可以使用字面量*/
    constructor(n:Int) : this("static") {
        index = n
        System.err.println(n)
    }

    constructor(n:Int,name:String) : this(name) {
        index = n
        System.err.println(n)
    }

}

/*===================================================================================*/

/*没有主构造函数*/
class ChildConstructor{

    /*有多个次构造函数*/
    constructor()

    constructor(name: String)

    constructor(age:Int)

}
/*===================================================================================*/
/**
 * 如果一个非抽象类没有声明任何（主或次）构造函数，
 * 它会有一个生成的不带参数的主构造函数。
 * 构造函数的可见性是 public。
 * 如果你不希望你的类有一个公有构造函数，你需要声明一个带有非默认可见性的空的主构造函数：
 */
class DontCreateMe private constructor () { /*……*/ }

/*===================================================================================*/

/**
 * 在 JVM 上，如果主构造函数的所有的参数都有默认值，
 * 编译器会生成 一个额外的无参构造函数，它将使用默认值。
 * 这使得 Kotlin 更易于使用像 Jackson 或者 JPA 这样的通过无参构造函数创建类的实例的库。
 */
class Customer(val customerName: String = "ABCDDEF"){

    fun name(){
        System.err.println(customerName)
    }

}



fun main() {
    val constructorNotice = ConstructorNotice("ABC")
    val constructorNotice1 = ConstructorNotice(5,"mama")

    val childConstructor = ChildConstructor(15)
    val childConstructor1 = ChildConstructor("Geo")

    val customer = Customer()
    customer.name()

    Customer("TEST").name()

    Exp().say()

}